/*
#
#    Copyright 2010, 2011 Artur Kornacki, hazeman11@gmail.com
#
#    This file is part of Pyrit.
#
#    Pyrit is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    Pyrit is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with Pyrit.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <cal/cal.hpp>
#include <cal/cal_il.hpp>

using namespace cal::il;

struct SHA_DEV_CTX 
{
    uint2 h0,h1,h2,h3,h4;

    void assign( const uint2& a, const uint2& b, const uint2& c, const uint2& d, const uint2& e )
    {
        h0 = a; h1 = b; h2 = c; h3 = d; h4 = e;
    }

    SHA_DEV_CTX& operator^=( const SHA_DEV_CTX& v )
    {
        h0 = h0 ^ v.h0;
        h1 = h1 ^ v.h1;
        h2 = h2 ^ v.h2;
        h3 = h3 ^ v.h3;
        h4 = h4 ^ v.h4;

        return *this;
    }
};

/* This function is generated by generate_optimized_kernel script */
static void sha1_process( const SHA_DEV_CTX& ctx, SHA_DEV_CTX& data )
{
  uint2 temp693;
  uint2 D690;
  uint2 B689;
  uint2 temp683;
  uint2 E680;
  uint2 C679;
  uint2 temp673;
  uint2 A670;
  uint2 D669;
  uint2 temp668;
  uint2 temp663;
  uint2 B660;
  uint2 E659;
  uint2 temp658;
  uint2 temp653;
  uint2 C650;
  uint2 A649;
  uint2 temp648;
  uint2 temp643;
  uint2 D640;
  uint2 B639;
  uint2 temp638;
  uint2 temp633;
  uint2 E630;
  uint2 C629;
  uint2 temp628;
  uint2 temp623;
  uint2 A620;
  uint2 D619;
  uint2 temp618;
  uint2 temp613;
  uint2 B610;
  uint2 E609;
  uint2 temp608;
  uint2 temp603;
  uint2 C600;
  uint2 A599;
  uint2 temp598;
  uint2 temp593;
  uint2 D590;
  uint2 B589;
  uint2 temp588;
  uint2 temp583;
  uint2 E580;
  uint2 C579;
  uint2 temp578;
  uint2 temp573;
  uint2 A570;
  uint2 D569;
  uint2 temp568;
  uint2 temp563;
  uint2 B560;
  uint2 E559;
  uint2 temp558;
  uint2 temp553;
  uint2 C550;
  uint2 A549;
  uint2 temp548;
  uint2 temp543;
  uint2 D540;
  uint2 B539;
  uint2 temp538;
  uint2 temp533;
  uint2 E530;
  uint2 C529;
  uint2 temp528;
  uint2 temp523;
  uint2 A520;
  uint2 D519;
  uint2 temp518;
  uint2 temp513;
  uint2 B510;
  uint2 E509;
  uint2 temp508;
  uint2 temp503;
  uint2 C500;
  uint2 A499;
  uint2 temp498;
  uint2 temp491;
  uint2 D488;
  uint2 B487;
  uint2 temp486;
  uint2 temp479;
  uint2 E476;
  uint2 C475;
  uint2 temp474;
  uint2 temp467;
  uint2 A464;
  uint2 D463;
  uint2 temp462;
  uint2 temp455;
  uint2 B452;
  uint2 E451;
  uint2 temp450;
  uint2 temp443;
  uint2 C440;
  uint2 A439;
  uint2 temp438;
  uint2 temp431;
  uint2 D428;
  uint2 B427;
  uint2 temp426;
  uint2 temp419;
  uint2 E416;
  uint2 C415;
  uint2 temp414;
  uint2 temp407;
  uint2 A404;
  uint2 D403;
  uint2 temp402;
  uint2 temp395;
  uint2 B392;
  uint2 E391;
  uint2 temp390;
  uint2 temp383;
  uint2 C380;
  uint2 A379;
  uint2 temp378;
  uint2 temp371;
  uint2 D368;
  uint2 B367;
  uint2 temp366;
  uint2 temp359;
  uint2 E356;
  uint2 C355;
  uint2 temp354;
  uint2 temp347;
  uint2 A344;
  uint2 D343;
  uint2 temp342;
  uint2 temp335;
  uint2 B332;
  uint2 E331;
  uint2 temp330;
  uint2 temp323;
  uint2 C320;
  uint2 A319;
  uint2 temp318;
  uint2 temp316;
  uint2 D314;
  uint2 B313;
  uint2 temp312;
  uint2 temp310;
  uint2 E308;
  uint2 C307;
  uint2 temp306;
  uint2 temp304;
  uint2 A302;
  uint2 D301;
  uint2 temp300;
  uint2 temp298;
  uint2 B296;
  uint2 E295;
  uint2 temp294;
  uint2 temp292;
  uint2 C290;
  uint2 A289;
  uint2 temp288;
  uint2 temp283;
  uint2 D281;
  uint2 B280;
  uint2 temp279;
  uint2 temp274;
  uint2 E273;
  uint2 C272;
  uint2 temp271;
  uint2 temp266;
  uint2 A265;
  uint2 D264;
  uint2 temp263;
  uint2 temp258;
  uint2 B257;
  uint2 E256;
  uint2 temp255;
  uint2 temp250;
  uint2 C248;
  uint2 A247;
  uint2 temp246;
  uint2 temp241;
  uint2 D239;
  uint2 B238;
  uint2 temp237;
  uint2 temp232;
  uint2 E231;
  uint2 C230;
  uint2 temp229;
  uint2 temp224;
  uint2 A223;
  uint2 D222;
  uint2 temp221;
  uint2 temp216;
  uint2 B215;
  uint2 E214;
  uint2 temp213;
  uint2 C208;
  uint2 A207;
  uint2 temp206;
  uint2 D201;
  uint2 B200;
  uint2 temp199;
  uint2 E194;
  uint2 C193;
  uint2 temp192;
  uint2 A187;
  uint2 D186;
  uint2 temp185;
  uint2 B180;
  uint2 E179;
  uint2 temp178;
  uint2 C173;
  uint2 A172;
  uint2 temp171;
  uint2 D168;
  uint2 B167;
  uint2 temp166;
  uint2 E163;
  uint2 C162;
  uint2 temp161;
  uint2 A158;
  uint2 D157;
  uint2 temp156;
  uint2 temp153;
  uint2 B152;
  uint2 E151;
  uint2 temp150;
  uint2 temp147;
  uint2 C146;
  uint2 A145;
  uint2 temp144;
  uint2 temp138;
  uint2 D137;
  uint2 B136;
  uint2 temp135;
  uint2 E128;
  uint2 C127;
  uint2 temp126;
  uint2 A119;
  uint2 D118;
  uint2 B112;
  uint2 E111;
  uint2 C106;
  uint2 A105;
  uint2 D99;
  uint2 B98;
  uint2 E92;
  uint2 C91;
  uint2 A85;
  uint2 D84;
  uint2 B78;
  uint2 E77;
  uint2 C71;
  uint2 A70;
  uint2 D64;
  uint2 B63;
  uint2 E57;
  uint2 C56;
  uint2 A50;
  uint2 D49;
  uint2 B43;
  uint2 E42;
  uint2 C37;
  uint2 A36;
  uint2 D35;
  uint2 B34;
  uint2 E33;
  uint2 C32;
  uint2 A31;
  uint2 D30;
  uint2 B29;
  uint2 E28;
  uint2 D;
  uint2 C;
  uint2 B;
  uint2 A;
  uint2 D2315;
  uint2 D2313;
  uint2 D2311;
  uint2 D2309;
  uint2 D2307;
  uint2 D2305;
  uint2 D2303;
  uint2 D2301;
  uint2 D2299;
  uint2 D2297;
  uint2 D2295;
  uint2 D2293;
  uint2 D2291;
  uint2 D2289;
  uint2 D2287;
  uint2 D2285;
  uint2 D2283;
  uint2 D2281;
  uint2 D2279;
  uint2 D2277;
  uint2 D2275;
  uint2 D2273;
  uint2 D2271;
  uint2 D2269;
  uint2 D2267;
  uint2 D2265;
  uint2 D2263;
  uint2 D2261;
  uint2 D2259;
  uint2 D2257;
  uint2 D2255;
  uint2 D2253;
  uint2 D2251;
  uint2 D2249;
  uint2 D2247;
  uint2 D2245;
  uint2 D2238;
  uint2 D2231;
  uint2 D2224;
  uint2 D2217;
  uint2 D2210;
  uint2 D2208;
  uint2 D2206;
  uint2 D2204;
  uint2 D2202;
  uint2 D2200;
  uint2 D2198;
  uint2 D2196;
  uint2 D2194;
  uint2 D2190;
  uint2 D2188;
  uint2 D2186;
  uint2 D2184;
  uint2 D2182;
  uint2 D2179;
  uint2 D2178;
  uint2 D2175;
  uint2 D2174;
  uint2 D2171;
  uint2 D2170;
  uint2 D2167;
  uint2 D2166;
  uint2 D2161;
  uint2 D2160;
  uint2 D2155;
  uint2 D2154;
  uint2 D2148;
  uint2 D2142;
  uint2 D2136;
  uint2 D2132;
  uint2 D2128;
  uint2 D2124;
  uint2 D2122;
  uint2 D2119;
  uint2 D2116;
  uint2 D2113;
  uint2 D2110;
  uint2 D2107;
  uint2 D2104;
  uint2 D2101;
  uint2 D2098;
  uint2 D2095;
  uint2 D2092;
  uint2 D2089;
  uint2 D2086;
  uint2 D2078;
  uint2 D2070;
  uint2 D2062;
  uint2 D2054;
  uint2 D2046;
  uint2 D2045;
  uint2 D2044;
  uint2 D2043;
  uint2 D2042;

  D2042 = data.h0;
  D2043 = data.h1;
  D2044 = data.h2;
  D2045 = data.h3;
  D2046 = data.h4;
  A = ctx.h0;
  B = ctx.h1;
  C = ctx.h2;
  D = ctx.h3;
  D2054 = ((D2042 + ctx.h4) + 0x5A827999) + rotate(A,32-27);
  E28 = D2054 + ((D ^ C) & B ^ D);
  B29 = rotate(B,32-2);
  D2062 = ((D2043 + D) + 0x5A827999) + ((B29 ^ C) & A ^ C);
  D30 = D2062 + rotate(E28,32-27);
  A31 = rotate(A,32-2);
  D2070 = ((D2044 + C) + 0x5A827999) + (E28 & (A31 ^ B29) ^ B29);
  C32 = D2070 + rotate(D30,32-27);
  E33 = rotate(E28,32-2);
  D2078 = ((D2045 + 0x5A827999) + B29) + ((E33 ^ A31) & D30 ^ A31);
  B34 = D2078 + rotate(C32,32-27);
  D35 = rotate(D30,32-2);
  D2086 = ((D2046 + 0x5A827999) + A31) + ((D35 ^ E33) & C32 ^ E33);
  A36 = D2086 + rotate(B34,32-27);
  C37 = rotate(C32,32-2);
  D2089 = (E33 + 3665983897) + ((C37 ^ D35) & B34 ^ D35);
  E42 = D2089 + rotate(A36,32-27);
  B43 = rotate(B34,32-2);
  D2092 = (D35 + 0x5A827999) + ((B43 ^ C37) & A36 ^ C37);
  D49 = D2092 + rotate(E42,32-27);
  A50 = rotate(A36,32-2);
  D2095 = (C37 + 0x5A827999) + ((A50 ^ B43) & E42 ^ B43);
  C56 = D2095 + rotate(D49,32-27);
  E57 = rotate(E42,32-2);
  D2098 = (B43 + 0x5A827999) + ((E57 ^ A50) & D49 ^ A50);
  B63 = D2098 + rotate(C56,32-27);
  D64 = rotate(D49,32-2);
  D2101 = (A50 + 0x5A827999) + ((D64 ^ E57) & C56 ^ E57);
  A70 = D2101 + rotate(B63,32-27);
  C71 = rotate(C56,32-2);
  D2104 = (E57 + 0x5A827999) + ((C71 ^ D64) & B63 ^ D64);
  E77 = D2104 + rotate(A70,32-27);
  B78 = rotate(B63,32-2);
  D2107 = (D64 + 0x5A827999) + ((B78 ^ C71) & A70 ^ C71);
  D84 = D2107 + rotate(E77,32-27);
  A85 = rotate(A70,32-2);
  D2110 = (C71 + 0x5A827999) + ((A85 ^ B78) & E77 ^ B78);
  C91 = D2110 + rotate(D84,32-27);
  E92 = rotate(E77,32-2);
  D2113 = (B78 + 0x5A827999) + ((E92 ^ A85) & D84 ^ A85);
  B98 = D2113 + rotate(C91,32-27);
  D99 = rotate(D84,32-2);
  D2116 = (A85 + 0x5A827999) + ((D99 ^ E92) & C91 ^ E92);
  A105 = D2116 + rotate(B98,32-27);
  C106 = rotate(C91,32-2);
  D2119 = (E92 + 1518500921) + ((C106 ^ D99) & B98 ^ D99);
  E111 = D2119 + rotate(A105,32-27);
  B112 = rotate(B98,32-2);
  D2122 = rotate((D2044 ^ D2042),32-31);
  D2124 = ((D2122 + 0x5A827999) + D99) + ((B112 ^ C106) & A105 ^ C106);
  D118 = D2124 + rotate(E111,32-27);
  A119 = rotate(A105,32-2);
  temp126 = rotate((D2045 ^ D2043),32-31);
  D2128 = ((temp126 + 0x5A827999) + C106) + ((A119 ^ B112) & E111 ^ B112);
  C127 = D2128 + rotate(D118,32-27);
  E128 = rotate(E111,32-2);
  temp135 = rotate(((D2044 ^ D2046) ^ 672),32-31);
  D2132 = ((temp135 + 0x5A827999) + B112) + ((E128 ^ A119) & D118 ^ A119);
  B136 = D2132 + rotate(C127,32-27);
  D137 = rotate(D118,32-2);
  temp138 = (D2045 ^ 0x80000000) ^ D2122;
  temp144 = rotate(temp138,32-31);
  D2136 = ((temp144 + 0x5A827999) + A119) + ((D137 ^ E128) & C127 ^ E128);
  A145 = D2136 + rotate(B136,32-27);
  C146 = rotate(C127,32-2);
  temp147 = temp126 ^ D2046;
  temp150 = rotate(temp147,32-31);
  D2142 = ((temp150 + 0x6ED9EBA1) + E128) + ((C146 ^ D137) ^ B136);
  E151 = D2142 + rotate(A145,32-27);
  B152 = rotate(B136,32-2);
  temp153 = temp135 ^ 0x80000000;
  temp156 = rotate(temp153,32-31);
  D2148 = ((temp156 + 0x6ED9EBA1) + D137) + ((B152 ^ C146) ^ A145);
  D157 = D2148 + rotate(E151,32-27);
  A158 = rotate(A145,32-2);
  temp161 = rotate(temp144,32-31);
  D2154 = ((temp161 + 0x6ED9EBA1) + C146) + ((A158 ^ B152) ^ E151);
  C162 = D2154 + rotate(D157,32-27);
  E163 = rotate(E151,32-2);
  D2155 = temp150 ^ 672;
  temp166 = rotate(D2155,32-31);
  D2160 = ((temp166 + 0x6ED9EBA1) + B152) + ((E163 ^ A158) ^ D157);
  B167 = D2160 + rotate(C162,32-27);
  D168 = rotate(D157,32-2);
  D2161 = temp156 ^ D2122;
  temp171 = rotate(D2161,32-31);
  D2166 = ((temp171 + 0x6ED9EBA1) + A158) + ((D168 ^ E163) ^ C162);
  A172 = D2166 + rotate(B167,32-27);
  C173 = rotate(C162,32-2);
  D2167 = temp161 ^ temp126;
  temp178 = rotate(D2167,32-31);
  D2170 = ((temp178 + 0x6ED9EBA1) + E163) + ((C173 ^ D168) ^ B167);
  E179 = D2170 + rotate(A172,32-27);
  B180 = rotate(B167,32-2);
  D2171 = temp166 ^ temp135;
  temp185 = rotate(D2171,32-31);
  D2174 = ((temp185 + 0x6ED9EBA1) + D168) + ((B180 ^ C173) ^ A172);
  D186 = D2174 + rotate(E179,32-27);
  A187 = rotate(A172,32-2);
  D2175 = temp171 ^ temp144;
  temp192 = rotate(D2175,32-31);
  D2178 = ((temp192 + 0x6ED9EBA1) + C173) + ((A187 ^ B180) ^ E179);
  C193 = D2178 + rotate(D186,32-27);
  E194 = rotate(E179,32-2);
  D2179 = temp178 ^ temp150;
  temp199 = rotate(D2179,32-31);
  D2182 = ((temp199 + 0x6ED9EBA1) + B180) + ((E194 ^ A187) ^ D186);
  B200 = D2182 + rotate(C193,32-27);
  D201 = rotate(D186,32-2);
  D2184 = (temp156 ^ 672) ^ temp185;
  temp206 = rotate(D2184,32-31);
  D2186 = ((temp206 + 0x6ED9EBA1) + A187) + ((D201 ^ E194) ^ C193);
  A207 = D2186 + rotate(B200,32-27);
  C208 = rotate(C193,32-2);
  D2188 = (temp161 ^ D2122) ^ temp192;
  temp213 = rotate(D2188,32-31);
  D2190 = ((temp213 + 0x6ED9EBA1) + E194) + ((C208 ^ D201) ^ B200);
  E214 = D2190 + rotate(A207,32-27);
  B215 = rotate(B200,32-2);
  temp216 = ((temp126 ^ 672) ^ temp166) ^ temp199;
  temp221 = rotate(temp216,32-31);
  D2194 = ((temp221 + 0x6ED9EBA1) + D201) + ((B215 ^ C208) ^ A207);
  D222 = D2194 + rotate(E214,32-27);
  A223 = rotate(A207,32-2);
  temp224 = ((temp135 ^ D2122) ^ temp171) ^ temp206;
  temp229 = rotate(temp224,32-31);
  D2196 = ((temp229 + 0x6ED9EBA1) + C208) + ((A223 ^ B215) ^ E214);
  C230 = D2196 + rotate(D222,32-27);
  E231 = rotate(E214,32-2);
  temp232 = ((temp144 ^ temp126) ^ temp178) ^ temp213;
  temp237 = rotate(temp232,32-31);
  D2198 = ((temp237 + 0x6ED9EBA1) + B215) + ((E231 ^ A223) ^ D222);
  B238 = D2198 + rotate(C230,32-27);
  D239 = rotate(D222,32-2);
  temp241 = ((temp150 ^ temp135) ^ temp185) ^ temp221;
  temp246 = rotate(temp241,32-31);
  D2200 = ((temp246 + 0x6ED9EBA1) + A223) + ((D239 ^ E231) ^ C230);
  A247 = D2200 + rotate(B238,32-27);
  C248 = rotate(C230,32-2);
  temp250 = ((temp156 ^ temp144) ^ temp192) ^ temp229;
  temp255 = rotate(temp250,32-31);
  D2202 = ((temp255 + 0x6ED9EBA1) + E231) + ((C248 ^ D239) ^ B238);
  E256 = D2202 + rotate(A247,32-27);
  B257 = rotate(B238,32-2);
  temp258 = ((temp161 ^ temp150) ^ temp199) ^ temp237;
  temp263 = rotate(temp258,32-31);
  D2204 = ((temp263 + 0x6ED9EBA1) + D239) + ((B257 ^ C248) ^ A247);
  D264 = D2204 + rotate(E256,32-27);
  A265 = rotate(A247,32-2);
  temp266 = ((temp166 ^ temp156) ^ temp206) ^ temp246;
  temp271 = rotate(temp266,32-31);
  D2206 = ((temp271 + 0x6ED9EBA1) + C248) + ((A265 ^ B257) ^ E256);
  C272 = D2206 + rotate(D264,32-27);
  E273 = rotate(E256,32-2);
  temp274 = ((temp171 ^ temp161) ^ temp213) ^ temp255;
  temp279 = rotate(temp274,32-31);
  D2208 = ((temp279 + 0x6ED9EBA1) + B257) + ((E273 ^ A265) ^ D264);
  B280 = D2208 + rotate(C272,32-27);
  D281 = rotate(D264,32-2);
  temp283 = ((temp178 ^ temp166) ^ temp221) ^ temp263;
  temp288 = rotate(temp283,32-31);
  D2210 = ((temp288 + 0x6ED9EBA1) + A265) + ((D281 ^ E273) ^ C272);
  A289 = D2210 + rotate(B280,32-27);
  C290 = rotate(C272,32-2);
  temp292 = ((temp185 ^ temp171) ^ temp229) ^ temp271;
  temp294 = rotate(temp292,32-31);
  D2217 = ((temp294 + 0x8F1BBCDC) + E273) + rotate(A289,32-27);
  E295 = D2217 + ((B280 | C290) & D281 | B280 & C290);
  B296 = rotate(B280,32-2);
  temp298 = ((temp192 ^ temp178) ^ temp237) ^ temp279;
  temp300 = rotate(temp298,32-31);
  D2224 = ((temp300 + 0x8F1BBCDC) + D281) + ((A289 | B296) & C290 | A289 & B296);
  D301 = D2224 + rotate(E295,32-27);
  A302 = rotate(A289,32-2);
  temp304 = ((temp199 ^ temp185) ^ temp246) ^ temp288;
  temp306 = rotate(temp304,32-31);
  D2231 = ((temp306 + 0x8F1BBCDC) + C290) + rotate(D301,32-27);
  C307 = D2231 + ((E295 | A302) & B296 | E295 & A302);
  E308 = rotate(E295,32-2);
  temp310 = ((temp206 ^ temp192) ^ temp255) ^ temp294;
  temp312 = rotate(temp310,32-31);
  D2238 = ((temp312 + 0x8F1BBCDC) + B296) + ((D301 | E308) & A302 | D301 & E308);
  B313 = D2238 + rotate(C307,32-27);
  D314 = rotate(D301,32-2);
  temp316 = ((temp213 ^ temp199) ^ temp263) ^ temp300;
  temp318 = rotate(temp316,32-31);
  D2245 = ((temp318 + 0x8F1BBCDC) + A302) + rotate(B313,32-27);
  A319 = D2245 + ((C307 | D314) & E308 | C307 & D314);
  C320 = rotate(C307,32-2);
  temp323 = ((temp221 ^ temp206) ^ temp271) ^ temp306;
  temp330 = rotate(temp323,32-31);
  D2247 = ((temp330 + 0x8F1BBCDC) + E308) + ((B313 | C320) & D314 | B313 & C320);
  E331 = D2247 + rotate(A319,32-27);
  B332 = rotate(B313,32-2);
  temp335 = ((temp229 ^ temp213) ^ temp279) ^ temp312;
  temp342 = rotate(temp335,32-31);
  D2249 = ((temp342 + 0x8F1BBCDC) + D314) + rotate(E331,32-27);
  D343 = D2249 + ((A319 | B332) & C320 | A319 & B332);
  A344 = rotate(A319,32-2);
  temp347 = ((temp237 ^ temp221) ^ temp288) ^ temp318;
  temp354 = rotate(temp347,32-31);
  D2251 = ((temp354 + 0x8F1BBCDC) + C320) + ((E331 | A344) & B332 | E331 & A344);
  C355 = D2251 + rotate(D343,32-27);
  E356 = rotate(E331,32-2);
  temp359 = ((temp246 ^ temp229) ^ temp294) ^ temp330;
  temp366 = rotate(temp359,32-31);
  D2253 = ((temp366 + 0x8F1BBCDC) + B332) + rotate(C355,32-27);
  B367 = D2253 + ((D343 | E356) & A344 | D343 & E356);
  D368 = rotate(D343,32-2);
  temp371 = ((temp255 ^ temp237) ^ temp300) ^ temp342;
  temp378 = rotate(temp371,32-31);
  D2255 = ((temp378 + 0x8F1BBCDC) + A344) + ((C355 | D368) & E356 | C355 & D368);
  A379 = D2255 + rotate(B367,32-27);
  C380 = rotate(C355,32-2);
  temp383 = ((temp263 ^ temp246) ^ temp306) ^ temp354;
  temp390 = rotate(temp383,32-31);
  D2257 = ((temp390 + 0x8F1BBCDC) + E356) + rotate(A379,32-27);
  E391 = D2257 + ((B367 | C380) & D368 | B367 & C380);
  B392 = rotate(B367,32-2);
  temp395 = ((temp271 ^ temp255) ^ temp312) ^ temp366;
  temp402 = rotate(temp395,32-31);
  D2259 = ((temp402 + 0x8F1BBCDC) + D368) + ((A379 | B392) & C380 | A379 & B392);
  D403 = D2259 + rotate(E391,32-27);
  A404 = rotate(A379,32-2);
  temp407 = ((temp279 ^ temp263) ^ temp318) ^ temp378;
  temp414 = rotate(temp407,32-31);
  D2261 = ((temp414 + 0x8F1BBCDC) + C380) + rotate(D403,32-27);
  C415 = D2261 + ((E391 | A404) & B392 | E391 & A404);
  E416 = rotate(E391,32-2);
  temp419 = ((temp288 ^ temp271) ^ temp330) ^ temp390;
  temp426 = rotate(temp419,32-31);
  D2263 = ((temp426 + 0x8F1BBCDC) + B392) + ((D403 | E416) & A404 | D403 & E416);
  B427 = D2263 + rotate(C415,32-27);
  D428 = rotate(D403,32-2);
  temp431 = ((temp294 ^ temp279) ^ temp342) ^ temp402;
  temp438 = rotate(temp431,32-31);
  D2265 = ((temp438 + 0x8F1BBCDC) + A404) + rotate(B427,32-27);
  A439 = D2265 + ((C415 | D428) & E416 | C415 & D428);
  C440 = rotate(C415,32-2);
  temp443 = ((temp300 ^ temp288) ^ temp354) ^ temp414;
  temp450 = rotate(temp443,32-31);
  D2267 = ((temp450 + 0x8F1BBCDC) + E416) + ((B427 | C440) & D428 | B427 & C440);
  E451 = D2267 + rotate(A439,32-27);
  B452 = rotate(B427,32-2);
  temp455 = ((temp306 ^ temp294) ^ temp366) ^ temp426;
  temp462 = rotate(temp455,32-31);
  D2269 = ((temp462 + 0x8F1BBCDC) + D428) + rotate(E451,32-27);
  D463 = D2269 + ((A439 | B452) & C440 | A439 & B452);
  A464 = rotate(A439,32-2);
  temp467 = ((temp312 ^ temp300) ^ temp378) ^ temp438;
  temp474 = rotate(temp467,32-31);
  D2271 = ((temp474 + 0x8F1BBCDC) + C440) + ((E451 | A464) & B452 | E451 & A464);
  C475 = D2271 + rotate(D463,32-27);
  E476 = rotate(E451,32-2);
  temp479 = ((temp318 ^ temp306) ^ temp390) ^ temp450;
  temp486 = rotate(temp479,32-31);
  D2273 = ((temp486 + 0x8F1BBCDC) + B452) + rotate(C475,32-27);
  B487 = D2273 + ((D463 | E476) & A464 | D463 & E476);
  D488 = rotate(D463,32-2);
  temp491 = ((temp330 ^ temp312) ^ temp402) ^ temp462;
  temp498 = rotate(temp491,32-31);
  D2275 = ((temp498 + 0x8F1BBCDC) + A464) + ((C475 | D488) & E476 | C475 & D488);
  A499 = D2275 + rotate(B487,32-27);
  C500 = rotate(C475,32-2);
  temp503 = ((temp342 ^ temp318) ^ temp414) ^ temp474;
  temp508 = rotate(temp503,32-31);
  D2277 = ((temp508 + 0xCA62C1D6) + E476) + ((C500 ^ D488) ^ B487);
  E509 = D2277 + rotate(A499,32-27);
  B510 = rotate(B487,32-2);
  temp513 = ((temp354 ^ temp330) ^ temp426) ^ temp486;
  temp518 = rotate(temp513,32-31);
  D2279 = ((temp518 + 0xCA62C1D6) + D488) + ((B510 ^ C500) ^ A499);
  D519 = D2279 + rotate(E509,32-27);
  A520 = rotate(A499,32-2);
  temp523 = ((temp366 ^ temp342) ^ temp438) ^ temp498;
  temp528 = rotate(temp523,32-31);
  D2281 = ((temp528 + 0xCA62C1D6) + C500) + ((A520 ^ B510) ^ E509);
  C529 = D2281 + rotate(D519,32-27);
  E530 = rotate(E509,32-2);
  temp533 = ((temp378 ^ temp354) ^ temp450) ^ temp508;
  temp538 = rotate(temp533,32-31);
  D2283 = ((temp538 + 0xCA62C1D6) + B510) + ((E530 ^ A520) ^ D519);
  B539 = D2283 + rotate(C529,32-27);
  D540 = rotate(D519,32-2);
  temp543 = ((temp390 ^ temp366) ^ temp462) ^ temp518;
  temp548 = rotate(temp543,32-31);
  D2285 = ((temp548 + 0xCA62C1D6) + A520) + ((D540 ^ E530) ^ C529);
  A549 = D2285 + rotate(B539,32-27);
  C550 = rotate(C529,32-2);
  temp553 = ((temp402 ^ temp378) ^ temp474) ^ temp528;
  temp558 = rotate(temp553,32-31);
  D2287 = ((temp558 + 0xCA62C1D6) + E530) + ((C550 ^ D540) ^ B539);
  E559 = D2287 + rotate(A549,32-27);
  B560 = rotate(B539,32-2);
  temp563 = ((temp414 ^ temp390) ^ temp486) ^ temp538;
  temp568 = rotate(temp563,32-31);
  D2289 = ((temp568 + 0xCA62C1D6) + D540) + ((B560 ^ C550) ^ A549);
  D569 = D2289 + rotate(E559,32-27);
  A570 = rotate(A549,32-2);
  temp573 = ((temp426 ^ temp402) ^ temp498) ^ temp548;
  temp578 = rotate(temp573,32-31);
  D2291 = ((temp578 + 0xCA62C1D6) + C550) + ((A570 ^ B560) ^ E559);
  C579 = D2291 + rotate(D569,32-27);
  E580 = rotate(E559,32-2);
  temp583 = ((temp438 ^ temp414) ^ temp508) ^ temp558;
  temp588 = rotate(temp583,32-31);
  D2293 = ((temp588 + 0xCA62C1D6) + B560) + ((E580 ^ A570) ^ D569);
  B589 = D2293 + rotate(C579,32-27);
  D590 = rotate(D569,32-2);
  temp593 = ((temp450 ^ temp426) ^ temp518) ^ temp568;
  temp598 = rotate(temp593,32-31);
  D2295 = ((temp598 + 0xCA62C1D6) + A570) + ((D590 ^ E580) ^ C579);
  A599 = D2295 + rotate(B589,32-27);
  C600 = rotate(C579,32-2);
  temp603 = ((temp462 ^ temp438) ^ temp528) ^ temp578;
  temp608 = rotate(temp603,32-31);
  D2297 = ((temp608 + 0xCA62C1D6) + E580) + ((C600 ^ D590) ^ B589);
  E609 = D2297 + rotate(A599,32-27);
  B610 = rotate(B589,32-2);
  temp613 = ((temp474 ^ temp450) ^ temp538) ^ temp588;
  temp618 = rotate(temp613,32-31);
  D2299 = ((temp618 + 0xCA62C1D6) + D590) + ((B610 ^ C600) ^ A599);
  D619 = D2299 + rotate(E609,32-27);
  A620 = rotate(A599,32-2);
  temp623 = ((temp486 ^ temp462) ^ temp548) ^ temp598;
  temp628 = rotate(temp623,32-31);
  D2301 = ((temp628 + 0xCA62C1D6) + C600) + ((A620 ^ B610) ^ E609);
  C629 = D2301 + rotate(D619,32-27);
  E630 = rotate(E609,32-2);
  temp633 = ((temp498 ^ temp474) ^ temp558) ^ temp608;
  temp638 = rotate(temp633,32-31);
  D2303 = ((temp638 + 0xCA62C1D6) + B610) + ((E630 ^ A620) ^ D619);
  B639 = D2303 + rotate(C629,32-27);
  D640 = rotate(D619,32-2);
  temp643 = ((temp508 ^ temp486) ^ temp568) ^ temp618;
  temp648 = rotate(temp643,32-31);
  D2305 = ((temp648 + 0xCA62C1D6) + A620) + ((D640 ^ E630) ^ C629);
  A649 = D2305 + rotate(B639,32-27);
  C650 = rotate(C629,32-2);
  temp653 = ((temp518 ^ temp498) ^ temp578) ^ temp628;
  temp658 = rotate(temp653,32-31);
  D2307 = ((temp658 + 0xCA62C1D6) + E630) + ((C650 ^ D640) ^ B639);
  E659 = D2307 + rotate(A649,32-27);
  B660 = rotate(B639,32-2);
  temp663 = ((temp528 ^ temp508) ^ temp588) ^ temp638;
  temp668 = rotate(temp663,32-31);
  D2309 = ((temp668 + 0xCA62C1D6) + D640) + ((B660 ^ C650) ^ A649);
  D669 = D2309 + rotate(E659,32-27);
  A670 = rotate(A649,32-2);
  temp673 = ((temp538 ^ temp518) ^ temp598) ^ temp648;
  D2311 = ((rotate(temp673,32-31) + 0xCA62C1D6) + C650) + ((A670 ^ B660) ^ E659);
  C679 = D2311 + rotate(D669,32-27);
  E680 = rotate(E659,32-2);
  temp683 = ((temp548 ^ temp528) ^ temp608) ^ temp658;
  D2313 = ((rotate(temp683,32-31) + 0xCA62C1D6) + B660) + ((E680 ^ A670) ^ D669);
  B689 = D2313 + rotate(C679,32-27);
  D690 = rotate(D669,32-2);
  temp693 = ((temp558 ^ temp538) ^ temp618) ^ temp668;
  D2315 = ((A + 0xCA62C1D6) + rotate(temp693,32-31)) + A670;
  data.h0 = (D2315 + ((D690 ^ E680) ^ C679)) + rotate(B689,32-27);
  data.h1 = B689 + ctx.h1;
  data.h2 = rotate(C679,32-2) + ctx.h2;
  data.h3 = D690 + ctx.h3;
  data.h4 = E680 + ctx.h4;
}

static void calpp_pmk_kernel( const input2d<uint4>& inbuffer0,  const input2d<uint4>& inbuffer1, const input2d<uint4>& inbuffer2,  const input2d<uint4>& inbuffer3, const input2d<uint4>& inbuffer4,
                              named_variable<uint4>& outbuffer0, named_variable<uint4>& outbuffer1 )
{
    SHA_DEV_CTX temp_ctx, pmk_ctx, ctx_ipad, ctx_opad;
    uint4       iv0,iv1,iv2,iv3,iv4;
    int1        i;

    float2 idx = named_variable<float2>("vWinCoord0.xy");

    // loading ipad,opad,temp_ctx
    iv0 = inbuffer0[idx];
    iv1 = inbuffer1[idx];
    iv2 = inbuffer2[idx];
    iv3 = inbuffer3[idx];
    iv4 = inbuffer4[idx];

    // unpacking data from input buffers
    ctx_ipad.assign( iv0.xx(), iv0.yy(), iv0.zz(), iv0.ww(), iv1.xx() );
    ctx_opad.assign( iv1.yy(), iv1.zz(), iv1.ww(), iv2.xx(), iv2.yy() );
    temp_ctx.assign( uint2(iv2.z(),iv3.w()),
                     uint2(iv2.w(),iv4.x()),
                     uint2(iv3.x(),iv4.y()),
                     uint2(iv3.y(),iv4.z()),
                     uint2(iv3.z(),iv4.w()) );

    pmk_ctx = temp_ctx;
    i = 4096;
    il_whileloop {
        i += -1;
        il_breakc( !i );

        sha1_process( ctx_ipad, temp_ctx );
        sha1_process( ctx_opad, temp_ctx );
        pmk_ctx ^= temp_ctx;
    } il_endloop

    outbuffer0 = uint4( pmk_ctx.h0.x(), pmk_ctx.h1.x(), pmk_ctx.h2.x(), pmk_ctx.h3.x() );
    outbuffer1 = uint4( pmk_ctx.h4.x(), pmk_ctx.h0.y(), pmk_ctx.h1.y(), pmk_ctx.h2.y() );
}

std::string calpp_create_pmk_kernel( cal::Device& device )
{
    std::stringstream code;

    code << "il_ps_2_0\n";
    code << "dcl_input_position_interp(linear_noperspective) vWinCoord0.xy__\n";

    Source::begin(device);

    input2d<uint4>        inbuffer0(0),inbuffer1(1),inbuffer2(2),inbuffer3(3),inbuffer4(4);
    named_variable<uint4> outbuffer0("o0"),outbuffer1("o1");

    calpp_pmk_kernel(inbuffer0,inbuffer1,inbuffer2,inbuffer3,inbuffer4,
                     outbuffer0,outbuffer1);

    Source::end();

    Source::emitHeader(code);
    Source::emitCode(code);

    code << "end\n";

    return code.str();
}
